package com.uwo.commons.apollo.configuration;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.config.ConfigPropertySource;
import com.ctrip.framework.apollo.spring.config.PropertySourcesConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.ConfigurableEnvironment;

/**
 * apollo 配置监听
 * @author hao.yan
 */
public class ApolloListenter implements ApplicationListener<ApplicationEvent> {

    private final Logger log = LoggerFactory.getLogger(ApolloListenter.class);

    private static final String NAMESPACES = "apollo.namespaces";

    private static final String REFRESH_SCOPE = "refreshScope";

    private RefreshScope refreshScope;

    /**
     * 监听
     * @param event
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        // 配置信息监听
        if(event  instanceof ApplicationEnvironmentPreparedEvent){
            ConfigurableEnvironment environment = ((ApplicationEnvironmentPreparedEvent)event).getEnvironment();
            if(environment.containsProperty(NAMESPACES)) {
                String namespaces_str = environment.getProperty(NAMESPACES, ConfigConsts.NAMESPACE_APPLICATION);
                if (log.isDebugEnabled()) {
                    log.debug("Apollo bootstrap namespaces: {}", namespaces_str);
                }
                String[] namespaces = namespaces_str.split(",");
                CompositePropertySource composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME);
                for (String namespace : namespaces) {
                    Config config = ConfigService.getConfig(namespace);
                    composite.addPropertySource(new ConfigPropertySource(namespace, config));
                    config.addChangeListener(configChangeListener);
                }
                environment.getPropertySources().addFirst(composite);
            }
        }
        // bean注入监听
        if (event instanceof ApplicationPreparedEvent) {
            ConfigurableApplicationContext applicationContext = ((ApplicationPreparedEvent)event).getApplicationContext();
            if(applicationContext.containsBean(REFRESH_SCOPE))
                refreshScope = applicationContext.getBean(RefreshScope.class);
        }

    }

    private ConfigChangeListener configChangeListener = new ApolloConfigChangeListener();

    /**
     * properties更新监听
     */
    class ApolloConfigChangeListener implements ConfigChangeListener {
        @Override
        public void onChange(ConfigChangeEvent changeEvent) {
            log.info("apollo config change namespace = {}", changeEvent.getNamespace());
            refreshScope.refreshAll();
        }
    }

}
